package com.jindianjichi.basic.service.impl;


import com.jindianjichi.basic.entity.EsSubjectFields;
import com.jindianjichi.basic.entity.SubjectInfoEs;
import com.jindianjichi.basic.es.EsIndexInfo;
import com.jindianjichi.basic.es.EsRestClint;
import com.jindianjichi.basic.es.EsSearchRequest;
import com.jindianjichi.basic.es.EsSourceData;
import com.jindianjichi.basic.service.SubejectEsService;
import com.jindianjichi.subject.common.entity.PageResult;
import com.jindianjichi.subject.common.enums.SubjectInfoTypeEnum;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.*;

@Service
@Slf4j
public class SubejectEsServiceImpl implements SubejectEsService {


    @Override
    public Boolean insert(SubjectInfoEs subjectInfoEs) {
        EsSourceData esSourceData = new EsSourceData();
        Map<String, Object> data = convert2EsSourceData(subjectInfoEs);
        esSourceData.setDocId(subjectInfoEs.getDocId().toString());
        esSourceData.setData(data);

        return EsRestClint.insertDoc(getEsIndexInfo(), esSourceData);
    }

    @Override
    public PageResult<SubjectInfoEs> querySubjectList(SubjectInfoEs req) {
        PageResult<SubjectInfoEs> pageResult = new PageResult<>();
        EsSearchRequest esSearchRequest = new EsSearchRequest();
        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
        esSearchRequest = createSearchListQuery(req);
        SearchResponse searchResponse = EsRestClint.searchWithTermQuery(getEsIndexInfo(), esSearchRequest);
        List<SubjectInfoEs> subjectInfoEsList = new LinkedList<>();
        SearchHits serachHits = searchResponse.getHits();
        if (serachHits == null || serachHits.getHits() == null) {
            pageResult.setPageSize(req.getPageSize());
            pageResult.setPageNo(req.getPageNo());
            pageResult.setRecords(subjectInfoEsList);
            pageResult.setTotal(0);
            return pageResult;
        }
        SearchHit[] hits = serachHits.getHits();
        for (SearchHit hit : hits) {
            SubjectInfoEs subjectInfoEs = convert2SubjectInfoEs(hit);
            subjectInfoEsList.add(subjectInfoEs);
        }

        pageResult.setPageSize(req.getPageSize());
        pageResult.setPageNo(req.getPageNo());
        pageResult.setRecords(subjectInfoEsList);
        pageResult.setTotal((int) serachHits.getTotalHits().value);
        pageResult.setRecords(subjectInfoEsList);

        return pageResult;
    }

    private SubjectInfoEs convert2SubjectInfoEs(SearchHit hit) {
        SubjectInfoEs subjectInfoEs = new SubjectInfoEs();
        Map<String, Object> sourceAsMap = hit.getSourceAsMap();
        if (CollectionUtils.isEmpty(sourceAsMap)) {
            return null;
        }

        subjectInfoEs.setSubjectId(Long.valueOf(sourceAsMap.get(EsSubjectFields.SUBJECT_ID).toString()));
        subjectInfoEs.setDocId(Long.valueOf(sourceAsMap.get(EsSubjectFields.DOC_ID).toString()));
        subjectInfoEs.setSubjectName(sourceAsMap.get(EsSubjectFields.SUBJECT_NAME).toString());
        subjectInfoEs.setSubjectAnswer(sourceAsMap.get(EsSubjectFields.SUBJECT_ANSWER).toString());
        subjectInfoEs.setSubjectType(Integer.valueOf(sourceAsMap.get(EsSubjectFields.SUBJECT_TYPE).toString()));
        subjectInfoEs.setScore(new BigDecimal(hit.getScore()).multiply(new BigDecimal("100.00")).setScale(2, BigDecimal.ROUND_HALF_UP));
        //name高亮处理
        Map<String, HighlightField> highlightFields = hit.getHighlightFields();
        HighlightField subjectNameHighLight = highlightFields.get(EsSubjectFields.SUBJECT_NAME);
        if (Objects.nonNull(subjectNameHighLight)) {
            Text[] fragments = subjectNameHighLight.getFragments();
            StringBuilder subjectNameBulider = new StringBuilder();
            for (Text fragment : fragments) {
                subjectNameBulider.append(fragment);
            }
            subjectInfoEs.setSubjectName(subjectNameBulider.toString());

        }
            //answer高亮处理
            HighlightField subjectAnswerHighLight = highlightFields.get(EsSubjectFields.SUBJECT_ANSWER);
            if (Objects.nonNull(subjectAnswerHighLight)) {
                Text[] answerFragments = subjectAnswerHighLight.getFragments();
                StringBuilder subjectAnswerBulider = new StringBuilder();
                for (Text fragment : answerFragments) {
                    subjectAnswerBulider.append(fragment);
                }
                subjectInfoEs.setSubjectAnswer(subjectAnswerBulider.toString());


            }
            return subjectInfoEs;



    }

        private EsSearchRequest createSearchListQuery(SubjectInfoEs req){
            EsSearchRequest esSearchRequest = new EsSearchRequest();
            BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
            MatchQueryBuilder matchQueryBuilder = QueryBuilders.
                    matchQuery(EsSubjectFields.SUBJECT_NAME, req.getKeyWords());
            boolQueryBuilder.should(matchQueryBuilder);
            matchQueryBuilder.boost(2);
            MatchQueryBuilder matchAnswerQueryBuilder = QueryBuilders.
                    matchQuery(EsSubjectFields.SUBJECT_ANSWER, req.getKeyWords());
            boolQueryBuilder.should(matchAnswerQueryBuilder);
            MatchQueryBuilder matchTypeQueryBuilder = QueryBuilders.
                    matchQuery(EsSubjectFields.SUBJECT_TYPE, SubjectInfoTypeEnum.BRIEF.getCode());
            boolQueryBuilder.must(matchTypeQueryBuilder);
            boolQueryBuilder.minimumShouldMatch(1);
            esSearchRequest.setBq(boolQueryBuilder);
            //高亮
            HighlightBuilder highlightBuilder = new HighlightBuilder().
                    field("*").requireFieldMatch(false);
            highlightBuilder.preTags("<span style=\"color:red\">");
            highlightBuilder.postTags("</span>");
            esSearchRequest.setHighlightBuilder(highlightBuilder);
            esSearchRequest.setFields(EsSubjectFields.FIELD_QUERY);
            esSearchRequest.setFrom((req.getPageNo() - 1) * req.getPageSize());
            esSearchRequest.setSize(req.getPageSize());
            esSearchRequest.setNeedScroll(false);

            return esSearchRequest;
        }

        private EsIndexInfo getEsIndexInfo () {
            EsIndexInfo esIndexInfo = new EsIndexInfo();
            esIndexInfo.setClusterName("e70a7ba93527");
            esIndexInfo.setIndexName("subject_index");
            return esIndexInfo;
        }

        private Map<String, Object> convert2EsSourceData (SubjectInfoEs subjectInfoEs){
            Map<String, Object> data = new HashMap<>();
            data.put(EsSubjectFields.SUBJECT_ID, subjectInfoEs.getSubjectId());
            data.put(EsSubjectFields.DOC_ID, subjectInfoEs.getDocId());
            data.put(EsSubjectFields.SUBJECT_NAME, subjectInfoEs.getSubjectName());
            data.put(EsSubjectFields.SUBJECT_ANSWER, subjectInfoEs.getSubjectAnswer());
            data.put(EsSubjectFields.SUBJECT_TYPE, subjectInfoEs.getSubjectType());
            data.put(EsSubjectFields.CREATE_USER, subjectInfoEs.getCreateUser());
            data.put(EsSubjectFields.CREATE_TIME, subjectInfoEs.getCreateTime());
            return data;
        }





}
